"""
针对test02加锁

应该在类上加锁，保证类的安全性：
做到在某个线程对类实例进行加法或者减法操作时加锁，从而不让其他线程在同一时间对该实例进行加法或者减法操作。

加锁和解锁：
一般来说加锁后还要一些代码实现，在释放锁之前还有可能抛异常，一旦出现异常，锁是无法释放，但是当线程可能因为这个异常终止了，这就产生了死锁。

加锁、解锁常用语句：
1.使用try…finally语句保证锁的释放。
2.with上下文管理，锁对象支持上下文管理。
"""

from threading import Lock
import threading
import time


# 加法和减法
class Counter:
    def __init__(self):
        self._val = 0
        self.__lock = Lock()

    def add(self):
        try:
            self.__lock.acquire()
            self._val += 1
        finally:
            self.__lock.release()

    def sub(self):
        with self.__lock:
            self._val -= 1

    @property
    def show(self):
        with self.__lock:
            return self._val


# 实例化一个"加法和减法"的实例
d = Counter()


# 运算规则
def run(fn: Counter, count=100):
    for _ in range(count):
        for i in range(-50, 50):
            if i < 0:
                fn.sub()
            else:
                fn.add()


# num1，定义线程个数：越大线程越多。
# num2，定义单线程运算次数：越大单线程执行时间越长。
num1 = 10
num2 = 1000

for _ in range(num1):
    threading.Thread(target=run, args=(d, num2)).start()

# 主线程持续观察
while True:
    time.sleep(5)
    if threading.active_count() == 1:
        print(threading.enumerate())
        print(d.show)
        break
    else:
        print(threading.enumerate())